import java.util.ArrayList;
import java.util.List;

/**
 * Holds the names, hex codes, and operand types of all the machine ops in the language.<br><br>
 * Change Log:<br><br>
 * 	- 04/08/09 - Tobin Chee<br>
 * 		- Encapsulated tables within classes. Moved populateTable() methods to respective classes.<br><br>
 *  - 04/07/09 - Meghan Day<br>
 *  	- Populated machine ops.<br><br>
 *  - 04/13/09 - Meghan Day<br>
 *  	- Added machineOpsOperandTypes list and started populating it.<br><br>
 *  - 04/14/09 - Meghan Dar<br>
 *  	- Created and wrote getHexCode and getOperandType.<br><br>
 *  - 04/15/09 - Meghan Day<br>
 *  	- Changed machineOpsOperandTypes to integer rep<br><br>
 *  - 04/17/09 - Meghan Day<br>
 *  	- Updated documentation of operand types and (hopefully) finishing populating operand types.<br><br>
 *  - 04/18/09 - Meghan Day<br>
 *  	- Added some operations which were previously listed as directives.<br><br>
 *  - 04/19/09 - Meghan Day<br>
 *  	- Removed labelAllowed list and function<br><br>
 *  - 04/21/09 - Tobin Chee<br>
 *  	- Uppercased all incoming string queries to make parsing in Assembler.java easier<br><br>
 *  - 04/26/09 - Meghan Day<br>
 *  	- Filled out documentation.<br><br>
 *  - 05/03/09 - Meghan Day<br>
 *  	- Added items from change logs of operations to change log of the whole class, because
 *  	that's how it's supposed to be.<br><br>
 *  - 05/17/09 - Meghan Day<br>
 *  	- Added new types for DUMP and PWR.
 *  
 *  @author Tobin Chee, Meghan Day
 */
public class MachineOpsTable {
	/**
	 * Represents the names of all the machine ops.
	 */
	private List<String> machineOpsKey = new ArrayList<String>();
	/**
	 * Represents the hex codes of all the machine ops.
	 */
	private List<Integer> machineOpsHexCode = new ArrayList<Integer>();
	/**
	 * Represents which group of operations having similar operand the
	 * specific operation belongs to.<br>
	 * 0 - No operands<br>
	 * 1 - Mem_ref<br>
	 * 2 - Number or equated symbol<br>
	 * 3 - IOWD<br>
	 * 4 - EXR<br>
	 * 5 - CALL<br>
	 * 6 - EQU<br>
	 * 7 - EXTRN<br>
	 * 8 - String only<br>
	 * 9 - PRMID<br>
	 * 10 - ADRC<br>
	 * 11 - BSS<br>
	 * 12 - DEC<br>
	 * 13 - HEX<br>
	 * 14 - OCT<br>
	 * 15 - DEBUG<br>
	 * 16 - ALT<br>
	 * 17 - PRMLST<br>
	 * 18 - AVERT<br>
	 * 19 - DUMP<br>
	 * 20 - PWR<br>
	 */
	private List<Integer> machineOpsOperandTypes = new ArrayList<Integer>();
	
	/** Construct and populate a MachineOpsTable.
	 */
	public MachineOpsTable(){
		this.populateTable();
	}
	
	/**
	 * Returns the hexcode representing the operation, probably in decimal.
	 * @param key The operation name
	 * @return The hexcode of the operation as an integer<br><br>
	 * Change Log:<br>
	 * 	 - 04/14/09 - Meghan Day<br>
	 * 		- Created and wrote method
	 */
	public int getHexCode(String key) {
		key = key.toUpperCase();
		return machineOpsHexCode.get(machineOpsKey.indexOf(key));
	}
	
	/**
	 * Returns the integer corresponding to the operand group for the operation.
	 * @param key The operation name
	 * @return integer corresponding to the operand group of the operation<br><br>
	 * Change Log:<br>
	 *  - 04/14/09 - Meghan Day<br>
	 *  	- Created skeleton<br><br>
	 *  - 04/15/09 - Meghan Day<br>
	 *  	- Changed return value to int
	 */
	public int getOperandType(String key) {
		key = key.toUpperCase();
		return machineOpsOperandTypes.get(machineOpsKey.indexOf(key));
	}
	
	/**
	 * Checks to see if the operation with the given name is in the table.
	 * @param key The operation name to look for
	 * @return True if the string is in the table, false otherwise
	 */
	public boolean containsOp(String key){
		key = key.toUpperCase();
		return machineOpsKey.contains(key);
	}
	
	/** 
	 * Populates machineOpsKey with operation names, machineOpsHexCode with corresponding hex integers,
	 * and machineOpsOperandTypes with operand type numbers.<br><br>
	 * Change Log:<br>
	 * 	- 04/06/09 - Tobin Chee<br>
	 * 		- Created initial skeleton.<br><br>
	 *  - 04/07/09 - Meghan Day<br>
	 *  	- Populated machine ops.<br><br>
	 *  - 04/13/09 - Meghan Day<br>
	 *  	- Started populating operand types.<br><br>
	 *  - 04/15/09 - Meghan Day<br>
	 *  	- Changed table to fit with change in type of machineOpsOperandTypes.<br>
	 *  	- Populated more operand types.<br><br>
	 *  - 04/17/09 - Meghan Day<br>
	 *  	- Finished (hopefully) populating operand types.<br><br>
	 *  - 04/18/09 - Meghan Day<br>
	 *  	- Added some operations which were previously listed as directives.<br><br>
	 *  - 04/26/09 - Meghan Day<br>
	 *  	- Tweaked documentation
	 */
	private void populateTable(){
		
		machineOpsKey.add("ABS");
		machineOpsHexCode.add(0x51);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("ADD");
		machineOpsHexCode.add(0x40);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("ALS");
		machineOpsHexCode.add(0x37);
		machineOpsOperandTypes.add(2);
		
		machineOpsKey.add("ANA");
		machineOpsHexCode.add(0x30);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("ANS");
		machineOpsHexCode.add(0x31);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("ARS");
		machineOpsHexCode.add(0x38);
		machineOpsOperandTypes.add(2);
		
		machineOpsKey.add("AXR");
		machineOpsHexCode.add(0x65);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("BYRL");
		machineOpsHexCode.add(0x66);
		machineOpsOperandTypes.add(2);
		
		machineOpsKey.add("BYRR");
		machineOpsHexCode.add(0x67);
		machineOpsOperandTypes.add(2);
		
		machineOpsKey.add("CALL");
		machineOpsHexCode.add(0x7A);
		machineOpsOperandTypes.add(5);
		
		machineOpsKey.add("CAS");
		machineOpsHexCode.add(0x79);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("CHS");
		machineOpsHexCode.add(0x4E);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("CLA");
		machineOpsHexCode.add(0x4B);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("CLS");
		machineOpsHexCode.add(0x4C);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("DRXR");
		machineOpsHexCode.add(0x4D);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("DUMP");
		machineOpsHexCode.add(0xFE);
		machineOpsOperandTypes.add(19);
		
		machineOpsKey.add("DVH");
		machineOpsHexCode.add(0x44);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("DVP");
		machineOpsHexCode.add(0x45);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("EORA");
		machineOpsHexCode.add(0x36);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("EXR");
		machineOpsHexCode.add(0x25);
		machineOpsOperandTypes.add(4);
		
		machineOpsKey.add("HALT");
		machineOpsHexCode.add(0xFF);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("INCXR");
		machineOpsHexCode.add(0x46);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("IOWD");
		machineOpsHexCode.add(0x60);
		machineOpsOperandTypes.add(3);
		
		machineOpsKey.add("LD");
		machineOpsHexCode.add(0x00);
		machineOpsOperandTypes.add(1);
				
		machineOpsKey.add("LDMQ");
		machineOpsHexCode.add(0x01);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("LDX");
		machineOpsHexCode.add(0x02);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("LGLR");
		machineOpsHexCode.add(0x3A);
		machineOpsOperandTypes.add(2);
		
		machineOpsKey.add("LGSL");
		machineOpsHexCode.add(0x39);
		machineOpsOperandTypes.add(2);
		
		machineOpsKey.add("LOR");
		machineOpsHexCode.add(0x33);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("LORS");
		machineOpsHexCode.add(0x35);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("LXRA");
		machineOpsHexCode.add(0x10);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("LXRD");
		machineOpsHexCode.add(0x11);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("MOD");
		machineOpsHexCode.add(0x48);
		machineOpsOperandTypes.add(2);
		
		machineOpsKey.add("MODQ");
		machineOpsHexCode.add(0x49);
		machineOpsOperandTypes.add(2);
		
		machineOpsKey.add("MPR");
		machineOpsHexCode.add(0x42);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("MPY");
		machineOpsHexCode.add(0x43);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("NOP");
		machineOpsHexCode.add(0x47);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("OR");
		machineOpsHexCode.add(0x32);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("ORS");
		machineOpsHexCode.add(0x34);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("PAXR");
		machineOpsHexCode.add(0x26);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("PWR");
		machineOpsHexCode.add(0x4A);
		machineOpsOperandTypes.add(20);
		
		machineOpsKey.add("PXR");
		machineOpsHexCode.add(0x28);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("SARZ");
		machineOpsHexCode.add(0x50);
		machineOpsOperandTypes.add(0);
		
		machineOpsKey.add("SLW");
		machineOpsHexCode.add(0x24);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("ST");
		machineOpsHexCode.add(0x20);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("STMQ");
		machineOpsHexCode.add(0x21);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("STXR");
		machineOpsHexCode.add(0x22);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("STZ");
		machineOpsHexCode.add(0x23);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("SUB");
		machineOpsHexCode.add(0x41);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TACZ");
		machineOpsHexCode.add(0x72);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TMQO");
		machineOpsHexCode.add(0x73);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TMQP");
		machineOpsHexCode.add(0x74);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TNZ");
		machineOpsHexCode.add(0x71);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TPL");
		machineOpsHexCode.add(0x75);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TRA");
		machineOpsHexCode.add(0x70);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TSXR");
		machineOpsHexCode.add(0x76);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TXRL");
		machineOpsHexCode.add(0x77);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("TXRP");
		machineOpsHexCode.add(0x78);
		machineOpsOperandTypes.add(1);
		
		machineOpsKey.add("XCA");
		machineOpsHexCode.add(0x27);
		machineOpsOperandTypes.add(0);
		
	}
}
